package org.dromara.common.excel.core

import cn.idev.excel.context.AnalysisContext
import cn.idev.excel.event.AnalysisEventListener
import cn.idev.excel.exception.ExcelAnalysisException
import cn.idev.excel.exception.ExcelDataConvertException
import io.github.oshai.kotlinlogging.KotlinLogging
import jakarta.validation.ConstraintViolationException
import org.dromara.common.core.utils.StreamUtils.join
import org.dromara.common.core.utils.ValidatorUtils.validate
import org.dromara.common.json.utils.JsonUtils.toJsonString

/**
 * Excel 导入监听
 *
 * @author Yjoioooo
 * @author Lion Li
 * @updater LikeYouDo
 * @date 2025/1/9 13:41
 */
open class DefaultExcelListener<T>(
    /**
     * 是否Validator检验，默认为是
     */
    private var isValidate: Boolean = true

) : AnalysisEventListener<T>(), ExcelListener<T> {

    companion object {
        private val log = KotlinLogging.logger { }
    }

    /**
     * excel 表头数据
     */
    private lateinit var headMap: Map<Int, String>

    /**
     * 导入回执
     */
    private var excelResult: ExcelResult<T> = DefaultExcelResult()

    /**
     * 处理异常
     *
     * @param exception ExcelDataConvertException
     * @param context   Excel 上下文
     */
    @Throws(Exception::class)
    override fun onException(exception: Exception, context: AnalysisContext) {
        var errMsg: String? = null
        if (exception is ExcelDataConvertException) {
            // 如果是某一个单元格的转换异常 能获取到具体行号
            val rowIndex = exception.rowIndex
            val columnIndex = exception.columnIndex
            errMsg = "第${rowIndex + 1}行-第${columnIndex + 1}列-表头${headMap[columnIndex]}: 解析异常<br/>"
            if (log.isDebugEnabled()) {
                log.error { errMsg }
            }
        }
        if (exception is ConstraintViolationException) {
            val constraintViolations = exception.constraintViolations
            val constraintViolationsMsg = join(
                constraintViolations,
                { it?.message },
                ", "
            )
            errMsg = "第${context.readRowHolder().rowIndex + 1}行数据校验异常: $constraintViolationsMsg"
            if (log.isDebugEnabled()) {
                log.error { errMsg }
            }
        }
        excelResult.getErrorList().add(errMsg)
        throw ExcelAnalysisException(errMsg)
    }

    override fun invokeHeadMap(headMap: Map<Int, String>, context: AnalysisContext?) {
        this.headMap = headMap
        log.debug { "解析到一条表头数据: ${toJsonString(headMap)}" }
    }

    override fun invoke(data: T, context: AnalysisContext?) {
        if (isValidate) {
            validate(data)
        }
        excelResult.getList().add(data)
    }

    override fun doAfterAllAnalysed(context: AnalysisContext?) {
        log.debug { "所有数据解析完成！" }
    }

    override fun getExcelResult(): ExcelResult<T> {
        return excelResult
    }

}
